package com.campus.service.Impl;

import com.campus.constant.MessageConstant;
import com.campus.constant.StatusConstant;
import com.campus.dto.UserLoginDTO;
import com.campus.dto.UserRegisterDTO;
import com.campus.entity.User;
import com.campus.exception.AccountLockedException;
import com.campus.exception.AccountNotFoundException;
import com.campus.exception.PasswordErrorException;
import com.campus.exception.RegisterErrorException;
import com.campus.mapper.UserMapper;
import com.campus.service.UserService;
import com.campus.utils.AliyunSmsUtils;
import com.campus.utils.ValidateCodeUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;

/**
 * @author TaiZai
 * @data 2024/10/21 17:23
 */
@Slf4j
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 管理员登陆后台
     *
     * @param userLoginDTO
     * @return
     */
    @Override
    public User login(UserLoginDTO userLoginDTO) {
        Integer type = userLoginDTO.getType();
        User user = null;

        if (type == 1) {
            String username = userLoginDTO.getUsername();
            String password = userLoginDTO.getPassword();

            user = userMapper.getByUsername(username);
            // 用户不存在
            if(user == null) {
                throw new AccountNotFoundException(MessageConstant.ACCOUNT_NOT_FOUND);
            }

            // 密码比对
            // TODO: md加密再比对
            if (!password.equals(user.getPassword())) {
                throw new PasswordErrorException(MessageConstant.PASSWORD_ERROR);
            }
        } else if (type == 2) {
            String phone = userLoginDTO.getPhone();
            String code = userLoginDTO.getCode();

            // 校验验证码
            String key = "phone_code:" + userLoginDTO.getPhone();
            String phoneCode = userLoginDTO.getCode();
            String redisCode = stringRedisTemplate.opsForValue().get(key);
            if (!Objects.equals(phoneCode, redisCode)) {
                throw new RegisterErrorException(MessageConstant.PHONE_CODE_ERROR);
            }

            user = userMapper.getByPhone(userLoginDTO.getPhone());
        }

        // 账号被锁定
        if (user.getStatus() == StatusConstant.DISABLE) {
            throw new AccountLockedException(MessageConstant.ACCOUNT_LOCKED);
        }

        return user;
    }

    /**
     * 注册账号
     * @param userRegisterDTO
     */
    @Override
    public void register(UserRegisterDTO userRegisterDTO) {
        // 验证码验证
        String phone = userRegisterDTO.getPhone();
        String phoneCode = userRegisterDTO.getCode();

        String key = "phone_code:" + phone;
        String redisCode = stringRedisTemplate.opsForValue().get(key);

        if (!Objects.equals(phoneCode, redisCode)) {
            throw new RegisterErrorException(MessageConstant.PHONE_CODE_ERROR);
        }

        // 账号判重
        String username = userRegisterDTO.getUsername();
        User u = userMapper.getByUsername(username);
        if (u!= null) {
            throw new RegisterErrorException(MessageConstant.USERNAME_EXISTS);
        }

        // 注册成功，构造插入数据
        User user = User.builder()
                .username(userRegisterDTO.getUsername())
                .password(userRegisterDTO.getPassword())
                .phone(userRegisterDTO.getPhone())
                .roleId(3L)
                .createTime(LocalDateTime.now())
                .updateTime(LocalDateTime.now())
                .status(StatusConstant.ENABLE)
                .build();

        userMapper.addUser(user);
    }

    /**
     * 登录验证码
     * @param phone
     */
    @Override
    public void sendLoginCode(String phone) {
        // 查询账号是否存在
        User user = userMapper.getByPhone(phone);
        if (user == null) {
            throw new AccountNotFoundException(MessageConstant.ACCOUNT_NOT_FOUND);
        }

        if (Objects.equals(user.getStatus(), StatusConstant.DISABLE)) {
            throw new AccountLockedException(MessageConstant.ACCOUNT_LOCKED);
        }
        sendPhoneCode(phone);
    }

    /**
     * 发送注册验证码
     * @param phone
     */
    @Override
    public void sendRegisterCode(String phone) {
        // 查询账号是否存在
        User user = userMapper.getByPhone(phone);
        if (user != null) {
            throw new AccountNotFoundException(MessageConstant.ALREADY_EXISTS);
        }
        sendPhoneCode(phone);
    }

    /**
     * 发送短信验证码
     * @param phone
     */
    public void sendPhoneCode(String phone) {
        // 生成验证码
        Integer code = ValidateCodeUtils.generateValidateCode(6);

        // 发送短信验证码
        Map<String, String> params = Map.of(
                "phoneNumbers", phone,
                "signName", "多用户社区平台",
                "templateCode", "SMS_475245596",
                "templateParam", "{\"code\":\"" + code + "\"}"
        );

        try {
            Boolean sendResult = AliyunSmsUtils.sendSms(params);
            if (sendResult) {
                // 存入到 Redis
                String key = "phone_code:" + phone;
                stringRedisTemplate.opsForValue().set(key, String.valueOf(code));
                stringRedisTemplate.expire(key, 3, TimeUnit.MINUTES); // 3分钟过期
            }
        } catch (Exception e) {
            log.error("短信验证码发送失败：{}", e.getMessage());
            throw new RuntimeException("短信验证码发送失败");
        }
    }
}
